package internal

import (
	"common/api"
	"common/pkg/rabbitmq"
	"context"
	"dubbo.apache.org/dubbo-go/v3/config"
	"encoding/json"
	"fmt"
	Redis "github.com/go-redis/redis"
	_ "github.com/go-sql-driver/mysql"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

// todo 设置不同的redis
var redis *Redis.Client
var db *gorm.DB

type CommonServer struct {
	api.UnimplementedCommonServer
}

func (s *CommonServer) Update(_ context.Context, query *api.Value) (*api.Response, error) {
	sql := "REPLACE INTO " + query.Table + "(" + getKey(query.Key, ", ") + ") VALUE (" + getValue(query.Value) + ")"

	// 引入消息队列
	mq := rabbitmq.NewRabbitMQSimple("douyin")
	mq.PublishSimple(sql)

	return &api.Response{}, nil
}

func (s *CommonServer) Get(_ context.Context, query *api.Query) (*api.Response, error) {
	// 获取结果数组
	result := getResultType(query.Result)

	if query.Limit == nil {
		query.Limit = &api.Query_LimitLen{
			Start: 0,
			Len:   100,
		}
	}

	// 查询   表名/条件/跳过/限制/排序
	err := db.Table(query.Table).Where(getWhere(query.Where)).Offset(int(query.Limit.Start)).Limit(int(query.Limit.Len)).Order(getOrder(query.OrderBy)).Find(&result).Error
	if err != nil {
		return nil, err
	}

	// 转码后返回
	marshal, _ := json.Marshal(result)
	return &api.Response{
		Value: marshal,
	}, nil
}
func (s *CommonServer) Count(_ context.Context, query *api.Query) (*api.Response, error) {
	var count int64
	// 查询   表名/条件/跳过/限制/排序
	err := db.Table(query.Table).Where(getWhere(query.Where)).Count(&count).Error
	if err != nil {
		return nil, err
	}

	return &api.Response{
		Size: count,
	}, nil
}
func (s *CommonServer) Del(_ context.Context, query *api.Query) (*api.Response, error) {
	sql := "DELETE FROM " + query.Table + " WHERE " + getWhere(query.Where)
	err := db.Exec(sql).Error
	if err != nil {
		return nil, err
	}

	return &api.Response{}, nil
}
func (s *CommonServer) SetRedis(_ context.Context, value *api.Value) (*api.Response, error) {
	key := value.Database + ":" + value.Table + ":" + getKey(value.Key, ":")
	// 存在12小时
	err := redis.Set(key, value.Value[0], 12*60*1000*1000*1000).Err()
	if err != nil {
		return nil, err
	}
	return &api.Response{}, nil
}
func (s *CommonServer) GetRedis(_ context.Context, query *api.Query) (*api.Response, error) {
	key := query.Database + ":" + query.Table + ":" + getKey(query.Key, ":")
	result, err := redis.Get(key).Result()
	if err != nil {
		return nil, err
	}
	marshal, err := json.Marshal(result)
	if err != nil {
		return nil, err
	}
	return &api.Response{
		Value: marshal,
	}, nil
}

func init() {
	// redis
	redis = Redis.NewClient(&Redis.Options{
		Addr:     "139.159.188.186:6379", // redis地址
		Password: "124609",               // redis密码，没有则留空
		DB:       0,                      // 默认数据库，默认是0
	})

	// mysql
	var err error
	dsn := "admin:124609@tcp(139.159.188.186:3306)/douyin?charset=utf8&parseTime=True&loc=Local"
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})

	if err != nil {
		fmt.Println(err)
	}

	// 注册服务
	config.SetProviderService(&CommonServer{})
}

func getResultType(str api.Query_ResultType) interface{} {
	switch str {
	case api.Query_COMMENT:
		return []*api.Comment{}
	case api.Query_FAVOURITE:
		return []*api.Favourite{}
	case api.Query_MESSAGE:
		return []*api.Message{}
	case api.Query_RELATION:
		return []*api.UserRelation{}
	case api.Query_USER:
		return []*api.User{}
	case api.Query_VIDEO:
		return []*api.Video{}
	default:
		return []*api.Comment{}
	}
}

func getWhere(condition []*api.Query_Condition) (res string) {
	if condition == nil || len(condition) == 0 {
		return ""
	}

	AND := func(key []string, value []string, link []api.Query_Condition_ConditionType) (res string) {
		res += "("
		for index, _ := range key {
			if index != 0 {
				res += " AND "
			}

			var operator string
			switch link[index] {
			case api.Query_Condition_GT:
				operator = " > "
				break
			case api.Query_Condition_GE:
				operator = " >= "
				break
			case api.Query_Condition_LT:
				operator = " < "
				break
			case api.Query_Condition_LE:
				operator = " <= "
				break
			case api.Query_Condition_NE:
				operator = " = "
				break
			case api.Query_Condition_NEQ:
				operator = " != "
				break
			case api.Query_Condition_LIKE:
				operator = " LIKE "
				break
			default:
				operator = " = "
				break
			}
			res += key[index] + operator + "'" + value[index] + "'"
		}
		res += ")"
		return
	}

	for index, value := range condition {
		if index != 0 {
			res += " OR "
		}

		res += AND(value.Key, value.Value, value.Type)
	}
	return
}

func getOrder(order []*api.Query_Order) (res string) {
	if order == nil || len(order) == 0 {
		return ""
	}
	for index, value := range order {
		if index != 0 {
			res += ", "
		}

		var operator string
		switch value.Type {
		case api.Query_Order_ASC:
			operator = " ASC "
			break
		case api.Query_Order_DESC:
			operator = " DESC "
			break
		default:
			operator = " ASC "
			break
		}
		res += value.Key + operator
	}
	return
}

func getKey(key []string, char string) (res string) {
	for index, value := range key {
		if index != 0 {
			res += char
		}
		res += value
	}
	return
}

func getValue(value []string) (res string) {
	for index, value := range value {
		if index != 0 {
			res += ", "
		}
		res += "'" + value + "'"
	}
	return
}
